﻿/* Copyright © 2010 Nolics
Nolics.net and NSQLObjects are trademarks of Nolics.

Microsoft Public License (Ms-PL)

This license governs use of the accompanying software. If you use the software, you accept this license. If you do not accept the license, do not use the software.

1. Definitions
The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under U.S. copyright law.
A "contribution" is the original software, or any additions or changes to the software.
A "contributor" is any person that distributes its contribution under this license.
"Licensed patents" are a contributor's patent claims that read directly on its contribution.

2. Grant of Rights
(A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create.
(B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software.

3. Conditions and Limitations
(A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks.
(B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically.
(C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software.
(D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license.
(E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement. 
 */

using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using Microsoft.VisualStudio.Language.StandardClassification;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Classification;
using Microsoft.VisualStudio.Utilities;
using NSQLObjects.VS2010Plugin.Syntax;

namespace NSQLObjects.DBModelClassifier
{

    #region Provider definition
    /// <summary>
    /// This class causes a classifier to be added to the set of classifiers. Since 
    /// the content type is set to "text", this classifier applies to all text files
    /// </summary>
    [Export(typeof(IClassifierProvider))]
    [ContentType("dbmodel")]
    internal class DBModelClassifierProvider : IClassifierProvider
    {
        /// <summary>
        /// Import the classification registry to be used for getting a reference
        /// to the custom classification type later.
        /// </summary>
        [Import]
        internal IClassificationTypeRegistryService ClassificationRegistry = null; // Set via MEF

        internal IClassificationType CommentClassificationType { get; private set; }

        internal IClassificationType NumberClassificationType { get; private set; }

        internal IClassificationType KeywordClassificationType { get; private set; }

        internal IClassificationType StringClassificationType { get; private set; }

        internal IClassificationType ErrorClassificationType { get; private set; }

        internal IClassificationType SQLClassificationType { get; private set; }

        public IClassifier GetClassifier(ITextBuffer buffer) {
            if (CommentClassificationType == null) {
                CommentClassificationType = ClassificationRegistry.GetClassificationType(PredefinedClassificationTypeNames.Comment);
                NumberClassificationType = ClassificationRegistry.GetClassificationType(PredefinedClassificationTypeNames.Number);
                KeywordClassificationType = ClassificationRegistry.GetClassificationType(PredefinedClassificationTypeNames.Keyword);
                StringClassificationType = ClassificationRegistry.GetClassificationType(PredefinedClassificationTypeNames.String);
                SQLClassificationType = ClassificationRegistry.GetClassificationType("DBModelSQL");
            }
            return buffer.Properties.GetOrCreateSingletonProperty<Classifier>(() => new Classifier(this, buffer));
        }
    }
    #endregion //provider def

    class Classifier : IClassifier
    {
        public Classifier(DBModelClassifierProvider provider, ITextBuffer buffer) {
            this.provider = provider;
            this.buffer = buffer;
        }

        private ITextBuffer buffer;
        private DBModelClassifierProvider provider;

        #region IClassifier Members

#pragma warning disable 67
        public event EventHandler<ClassificationChangedEventArgs> ClassificationChanged;

        public IList<ClassificationSpan> GetClassificationSpans(SnapshotSpan span) {
            var snapShot = buffer.CurrentSnapshot;
            StringReader sr = new StringReader(snapShot.GetText());
            var sc = new Scanner(sr);
            var pr = new Parser(sc);
            pr.InitParser(provider, snapShot);
            pr.Parse();
            return pr.Classifications;
        }

        #endregion

    }
#if NEVER
    /// <summary>
    /// Classifier that classifies all text as an instance of the OrinaryClassifierType
    /// </summary>
    class DBModelClassifier : IClassifier
    {
        

        internal DBModelClassifier(IClassificationTypeRegistryService registry, ITextBuffer buffer) {
            _classificationType = registry.GetClassificationType(PredefinedClassificationTypeNames.Comment);
        }


        /// <summary>
        /// This method scans the given SnapshotSpan for potential matches for this classification.
        /// In this instance, it classifies everything and returns each span as a new ClassificationSpan.
        /// </summary>
        /// <param name="trackingSpan">The span currently being classified</param>
        /// <returns>A list of ClassificationSpans that represent spans identified to be of this classification</returns>
        public IList<ClassificationSpan> GetClassificationSpans(SnapshotSpan span) {
            //create a list to hold the results
            List<ClassificationSpan> classifications = new List<ClassificationSpan>();
            
            classifications.Add(new ClassificationSpan(new SnapshotSpan(span.Snapshot, new Span(span.Start, span.Length)),
                                                           _classificationType));
            return classifications;
        }

#pragma warning disable 67
        // This event gets raised if a non-text change would affect the classification in some way,
        // for example typing /* would cause the classification to change in C# without directly
        // affecting the span.
        public event EventHandler<ClassificationChangedEventArgs> ClassificationChanged;
#pragma warning restore 67
    }
#endif //Classifier
}
